package com.sf.dlb.service;

import com.sf.dlb.constant.ResponseConstant;
import com.sf.dlb.jpa.model.*;
import com.sf.dlb.jpa.repository.*;
import com.sf.dlb.mapper.dao.UserGradeMapper;
import com.sf.dlb.utils.Arith;
import com.sf.dlb.utils.DateUtils;

import com.sf.dlb.config.Global;
import com.sf.dlb.utils.GsonUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
/**
 * 计划任务service
 * Created by jing.tan on 2018/5/21.
 */
@Service
public class ScheduledTaskService {
    private static Logger logger = LoggerFactory.getLogger(ScheduledTaskService.class);

    @Autowired
    private UserWalletService userWalletService;
    @Autowired
    private UserNewRepository userNewRepository;
    @Autowired
    private UserInfoRepository userInfoRepository;
    @Autowired
    private UserInvitationRepository userInvitationRepository;
    @Autowired
    private UserGradeRepository userGradeRepository;
    @Autowired
    private NewRecodRepository newRecodRepository;
    @Autowired
    private UserGradeMapper userGradeMapper;
    @Autowired
    private UserShieldService userShieldService;
    @Resource
    public Global global;
    /**
     * 每天晚上的定时任务
     */
    @Scheduled(cron = "0 0 1 * * ?")
//    @Scheduled(cron = "0/5 * * * * ?")
    public void handlerUnlockDlb(){
        logger.info("handlerUnlockDlb start time = "+ DateUtils.getDateTime()+" & day="+global.wallet_dlb_unlock_time_day);
        //解锁列表
        userWalletService.checkUnlockDlb(global.wallet_dlb_unlock_time_day);
        Date yestDayDate=DateUtils.addDays(new Date(),-1);
        String yestDateStr=DateUtils.formatDate(yestDayDate,"yyyy-MM-dd");
        //阅读分成
        readGetdlbDivide(yestDateStr);
        //日分成-》TODO 只保留前面3个等级
//        moneyPoolDayDivide();
        //等级有效期
        handlerGradleValidity(yestDateStr);
        //每隔一个月收益减半;
        getDlbReduceHalf();
        //清理半个月之前的屏蔽列表
        userShieldService.clearShield();
        logger.info("handlerUnlockDlb start end = "+ DateUtils.getDateTime());
    }
    /**
     * 阅读分成
     */
    public void readGetdlbDivide(String yestDateStr){
        logger.info("readGetdlbDivide start "+yestDateStr);
        //购买了等级的用户
        List<UserInfo> userInfoList=userInfoRepository.findByBuyGradeAll();
        for (UserInfo userInfo:userInfoList) {
            //会员购买之后，需要隔一天才能有抽成 @TODO 太繁琐，不处理了
            String userGrade = userInfo.getUserGrade();
            String ownerUserId = userInfo.getUserId();
            //用户下线阅读分成倍数(百分比)
            UserGradeInfo userGradeInfo=userGradeRepository.findByGradeAndDelFlag(userGrade,"0");
            double multiple=Arith.div(userGradeInfo.getReadDivide(),100);
            //阅读总数
            double readGetDlbCount=0.0;
            //用户分成的数量
            double divideNumber;
            //用户邀请码那些人使用了，找出使用的用户
            List<UserInvitationInfo> invitationCodeInfos=userInvitationRepository.findByUserIdAndDelFlag(ownerUserId,"0");
            for (UserInvitationInfo userInvitationInfo:invitationCodeInfos) {
                //找出每个用户阅读的奖励；累加；
                String useUserId=userInvitationInfo.getInvitationUserId();
                Double userVeryDayReadGetdlbCount= newRecodRepository.getEveryDayReadGetdlb(useUserId,yestDateStr,"1","0"); //@lili
                userVeryDayReadGetdlbCount=(null==userVeryDayReadGetdlbCount?0.0:userVeryDayReadGetdlbCount);
                readGetDlbCount=readGetDlbCount+userVeryDayReadGetdlbCount;
            }
            //从中分成百分之20；给到购买等级的用户
            divideNumber=Arith.mul(readGetDlbCount,multiple);
            logger.info("readGetdlbDivide ownerUserId={},userGrade={},multiple={},readGetDlbCount={},divideNumber={}",ownerUserId,userGrade,multiple,readGetDlbCount,divideNumber);
            //@TODO divideNumber=0; 是否要显示记录
            if(divideNumber==0.0){
                logger.info("readGetdlbDivide divideNumber==0.0");
                continue;
            }
            //更新钱包，dlb流水
            String source= ResponseConstant.source_type_read_divide;
            String sourceDesc=ResponseConstant.source_type_read_divide_value;
            userWalletService.updateUserWallet(ownerUserId,divideNumber,source,sourceDesc);
        }
    }
    /**
     * 日分成
     */
    public void moneyPoolDayDivide(){
        logger.info("moneyPoolDayDivide start ");
        //找出用户购买了等级，并等级未过期，累计的购买金额,
        List<Map<String,Object>> userMoneyPoolList=userGradeMapper.getAllUserMoneyPoolCount();
        for (Map hashMap:userMoneyPoolList) {
            String userId= (String) hashMap.get("user_id");
            String userGrade= (String) hashMap.get("user_grade");
            BigDecimal userMoneyPoolCount= (BigDecimal) hashMap.get("moneyPoolCount");
            double userMoneyCountD=userMoneyPoolCount.doubleValue();
            //资金池分成百分比
            UserGradeInfo userGradeInfo=userGradeRepository.findByGradeAndDelFlag(userGrade,"0");
            Double moneyPoomDivide=userGradeInfo.getMoneyPoomDivide();
            double moneyPoolDivide=Arith.div(moneyPoomDivide,100);
            //分成数量
            double divideNumber=Arith.mul(userMoneyCountD,moneyPoolDivide);
            logger.info("moneyPoolDayDivide userId={},userGrade={},userMoneyCountD={},moneyPoolDivide={},divideNumber={}",userId,userGrade,userMoneyCountD,moneyPoolDivide,divideNumber);
            //@TODO divideNumber=0;是否要显示记录
            if(divideNumber==0.0){
                logger.info("moneyPoolDayDivide divideNumber==0.0");
                continue;
            }
            //更新钱包，dlb流水
            String source= ResponseConstant.source_type_money_pool_divide;
            String sourceDesc=ResponseConstant.source_type_money_pool_divide_value+":资金池:"+userMoneyCountD;
            userWalletService.updateUserWallet(userId,divideNumber,source,sourceDesc);
        }
    }
    /**
     * 等级有效期
     */
    public void handlerGradleValidity(String yestDateStr){
        logger.info("handlerGradleValidity start "+yestDateStr);
        //购买了等级用户，等级过期日期=当前日期;最后一次抽成，需要延迟到凌晨；
        List<UserInfo> userInfoList=userInfoRepository.findByBuGradeAndOverdueAll(yestDateStr);
        //更新过期了的用户等级信息
        List<UserInfo> userInfoListSave=new ArrayList<>();
        List<String> userIdList=new ArrayList<>();
        for (UserInfo userInfo:userInfoList) {
            userInfo.setUserGrade("0");//恢复到普通等级
            userInfo.setGradeValidityTime(null);
            userInfo.setUpdateDate(new Date());
            userInfoListSave.add(userInfo);
            userIdList.add(userInfo.getUserId());
        }
        logger.info("handlerGradleValidity userIdList.size={},userIdList={}",userIdList.size(), GsonUtils.getInstance().toJson(userIdList));
        userInfoRepository.save(userInfoListSave);
    }
    /**
     * 每隔一个月收益减半
     */
    public void getDlbReduceHalf(){
//        1》从来没有购买过等级；
//            1.1》从注册时间开始计算；
//            1.2》覆盖之前的减半次数；
        //历史数据以上线的时间计算
        String onlineStartTimeStr="2019-03-11";
        Date onlineStartTime=DateUtils.parseDate(onlineStartTimeStr);
        List<UserInfo> userInfoList=userGradeMapper.getNotBuyGradeUser();
        Date currentDate=new Date();
        logger.info("getDlbReduceHalf userInfoList.size={} ",userInfoList.size());
        for (UserInfo userInfo:userInfoList) {
            String userId=userInfo.getUserId();
            Date createDate=userInfo.getCreateDate();
            if(createDate.getTime()<=onlineStartTime.getTime()){
                logger.info("getDlbReduceHalf 历史数据收益减半以上线的时间 userId={},onlineStartTime={}",userId,DateUtils.formatDate(onlineStartTime));
                createDate=onlineStartTime;
            }
            double differDay=DateUtils.differDay(createDate,currentDate);
            double halveNumberD=Arith.div(differDay,30);
            int halveNumberI=(int)halveNumberD;
            logger.info("getDlbReduceHalf userId={},differDay={},halveNumberD={},halveNumberI={} ",userId,differDay,halveNumberD,halveNumberI);
            if(halveNumberI>0){
                UserNewInfo userNewInfo=userNewRepository.findByUserIdAndDelFlag(userId,"0");
                String updateRule=halveNumberI+",";
                userNewInfo.setReadGetdlbRule(updateRule);
                userNewInfo.setUpdateDate(new Date());
                userNewRepository.save(userNewInfo);
            }
        }
//        2》购买过等级，过期了；
//          2.1》从上次等级结束的日期开始计算；
//          2.2》需要更新之前的减半次数；
        List<UserGradeBuyRecordInfo> userGradeBuyRecordInfoList=userGradeMapper.getBuyGradeAndOverdueUser();
        logger.info("getDlbReduceHalf userGradeBuyRecordInfoList.size={} ",userGradeBuyRecordInfoList.size());
        for (UserGradeBuyRecordInfo userGradeBuyRecordInfo:userGradeBuyRecordInfoList) {
            String userId=userGradeBuyRecordInfo.getUserId();
            Date validityTime=userGradeBuyRecordInfo.getValidityTime();
            double differDay=DateUtils.differDay(validityTime,currentDate);
            double halveNumberD=Arith.div(differDay,30);
            int halveNumberI=(int)halveNumberD;
            logger.info("getDlbReduceHalf userId={},differDay={},halveNumberD={},halveNumberI={} ",userId,differDay,halveNumberD,halveNumberI);
            if(halveNumberI>0){
                UserNewInfo userNewInfo=userNewRepository.findByUserIdAndDelFlag(userId,"0");
                String readGetdlbRule=userNewInfo.getReadGetdlbRule();
                String updateReadGetdlbRule;
                if(StringUtils.isNotBlank(readGetdlbRule)){
                    String[] readGetdlbRuleSplit=readGetdlbRule.split(",");
                    int readGetdlbRule0=Integer.parseInt(readGetdlbRuleSplit[0]);
                    updateReadGetdlbRule=(readGetdlbRule0+halveNumberI)+",";
                }else{
                    updateReadGetdlbRule=halveNumberI+",";
                }
                userNewInfo.setReadGetdlbRule(updateReadGetdlbRule);
                userNewInfo.setUpdateDate(new Date());
                userNewRepository.save(userNewInfo);
            }
        }
    }
}
